Skip to content

Tutorials/Sim2Real Blogs: Add validated box benchmarks and viewer fixes. - #283

Merged
jnbntz merged 5 commits into
NVIDIA:mainfrom
johnnynunez:feature/blog2-validated-box-benchmark
Oct 14, 2026
Merged

jnbntz merged 5 commits into
NVIDIA:mainfrom
johnnynunez:feature/blog2-validated-box-benchmark

Conversation

@johnnynunez

Copy link
Copy Markdown
Contributor

The MuJoCo/MJWarp tutorial now uses the same two-cube receiving-box task on CPU and GPU: grasp, lift, carry, release, settle and withdraw. The lessons run reference solutions by default, preserve the learner exercises, and include the viewer completion and clean-exit fixes. This follows merged PR #279.

The new benchmark notebook starts in preflight mode. Its reproducible sweep compares 1, 16, 32, 64, 128, 256, 512, 1024 and 2048 worlds for SO-101 and reBot, with one full warm-up and five measured episodes. The retained workstation study accepted 35/36 configurations; reBot GPU512 remains excluded, with the original failure and timings preserved as diagnostic evidence. Raw archives, figures, package locks, hardware/configuration records and the separate ALOHA reference are included unchanged.

The tutorial and container use the measured MuJoCo 3.8.0 / MuJoCo Warp 3.8.0.3 / Warp 1.15.0 environment. It is intentionally separate from the Newton tutorial's 3.12 stack. Scoped LFS rules preserve the evidence payloads and figures; source MIT and model notices remain.

Validation: updated Docker image built; 151 tests passed, 1 optional viewer-integration test skipped, including both CPU/GPU robot tasks and real-kernel benchmark preflight. Four notebook format checks and source/LFS hash audits pass. The initial wrong-scope asset test and its corrected rerun are retained in hub-validation/2026-10-10.

These are community measurements on documented hardware, not official product benchmarks. The new container checks validate the Hub relocation; they do not replace the retained performance sweep. Live Brev and Colab execution remain unverified.

Fresh validation record: https://github.com/johnnynunez/accelerated-computing-hub/blob/e923560f71080d807b6d3be17c069dc2694fdbbc/tutorials/sim2real-blogs/hub-validation/2026-10-10/README.md

Refresh the MuJoCo/MJWarp lessons with the physically validated two-cube receiving-box task, matched CPU/GPU benchmark, finite viewer lifecycle, reproducible environments and unchanged raw evidence.

Follow-up to NVIDIA#279.

Signed-off-by: Johnny <johnnync13@gmail.com>
Bind the published notebooks and links to verified public Hub commits while retaining the measured runtime and original evidence.

Signed-off-by: Johnny <johnnync13@gmail.com>
Bind the published notebooks and links to verified public Hub commits while retaining the measured runtime and original evidence.

Signed-off-by: Johnny <johnnync13@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Oct 10, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown
Contributor

👋 Thank you for your contribution!

This pull request is from a forked repository so GitHub Actions will not be able to run CI. A maintainer will review your changes shortly and manually trigger the CI.

@maintainers Please review this PR when you have a chance and follow the instructions in the CONTRIBUTING.md file to trigger the CI.

…nd explain benchmarks.

A tester running the previous launch_passive lessons hit a window that never closed after stacking, ignored Space/Esc, and hung with GLXBadDrawable after Ctrl+C; the Part 2 command looked like Part 1 and the benchmark numbers were unexplained.

Port NVIDIA-dev/newton_blogs#2 (merge 281489d2cf47cf709a5420f066bb61e2827cdd33) into the Hub layout: every lesson run ends with a verified task result and exit code 0/1, Ctrl+C exits 130 within about a second in every phase (a second Ctrl+C immediately), slow rendering no longer slows the physics, and --benchmark/scaling_study print what each number measures and how it scales with GPU size. Add real-window X11 lifecycle tests and headless Ctrl+C tests, the validation record, and the updated migration manifest entries.

Signed-off-by: Johnny <johnnync13@gmail.com>
@johnnynunez

Copy link
Copy Markdown
Contributor Author

Update: commit 7ae10f1 ports the Article 2 viewer and benchmark fixes from NVIDIA-dev/newton_blogs#2 (merged as 281489d) into tutorials/sim2real-blogs/notebooks/mujoco. The commit is GitHub-signed and has a Signed-off-by trailer.

Why: tester report (13 Oct). The tester ran this tutorial's previous launch_passive lessons. After the red cube was stacked:

  • the window stayed open and the terminal never said "complete";
  • Space and Esc did nothing;
  • Ctrl+C printed a traceback, then X Error … GLXBadDrawable (X_GLXSwapBuffers), and the process ignored further Ctrl+C, so the terminal had to be killed.

They also found that the blog's Part 2 command "starts the same solution as Part 1": it is the one-world correctness check, and only --benchmark and scaling_study.py measure throughput. The benchmark numbers came with no explanation of what they are or how they scale with hardware. Under a real X server (Xvfb + Mesa, XTEST keys, window-manager close, SIGINT to the process group), the old code never exits, ignores Esc and Q, and on Ctrl+C prints a traceback followed by a glibc abort in the viewer teardown race.

What changed

  • Every lesson run (Part 1 and Part 2, solutions and scaffolds) ends with an explicit line and exit code:

    • Task complete: … (verified …) exits 0;
    • Task FAILED: … exits 1;
    • Esc, Q or closing the window stops the run and exits 0, with the task check skipped;
    • Ctrl+C exits 130.

    Stack runs are now checked against the article's thresholds instead of only printing diagnostics.

  • Ctrl+C: while the window is open, the SIGINT handler only sets a flag, and the main thread tears down GLFW/OpenGL itself. A wakeup-fd watcher exits the process on a second Ctrl+C, or when cleanup takes longer than 1 s (for example during Warp kernel compilation, which used to take 8.9 s and print a traceback).

  • Slow rendering: when rendering is slower than real time, the loop runs several physics frames per rendered frame instead of slowing the physics. Physics frames are never skipped.

  • Benchmark output: new part2/benchmark_report.py, used by --benchmark and scaling_study.py. The output now prints:

    • a header with GPU SMs/VRAM, CPU, timestep and a single-core mj_step baseline;
    • each column with its unit, plus aggregate real-time factor and peak VRAM;
    • a short reading guide;
    • a clean message on out-of-memory.
  • Docs: notebooks/mujoco/README.md gains controls and exit codes, the blog's Part 2 commands, and "Reading the benchmark numbers": RTX PRO 6000 numbers labelled as measured, RTX 5090 / RTX 3060 numbers labelled as expectations. Also updated: BENCHMARK.md, VIEWER_VALIDATION.md, VALIDATION.md, and a validation record under notebooks/mujoco/validation/viewer-exit-and-benchmark-2026-10-13/.

  • MIGRATION_MANIFEST.json: updated entries for the changed files and new entries for the added ones (each with source_commit = the newton_blogs merge), plus a source_updates record. Not ported: the source repo's root README and test_tutorial_scaffolds.py, which do not exist in this layout. Colab links, brev/, hub-validation/ evidence, licenses and the hash lock are unchanged.

  • Tests:

    • test/test_article2_viewer_x11.py: real-window GUI test. It needs DISPLAY and xdotool and skips cleanly without them, so the container suite skips it.
    • test/test_article2_ctrl_c.py: headless test with real signals.
    • test/x11_lifecycle_harness.py: shared harness.

Tests run on this exact tree (workstation with RTX PRO 6000 Blackwell, Article 2 hash lock: MuJoCo 3.8.0 / MuJoCo Warp 3.8.0.3 / Warp 1.15.0, outside Docker):

  • The brev/test.bash steps (nvidia-smi + pytest test/) with Xvfb, X11 and RUN_ARTICLE2_VIEWER_CPU_TESTS=1 enabled: 172 passed, 1 skipped (the opt-in ARTICLE2_NOTEBOOKS_EXECUTE notebook preflight). This includes 12 X11 lifecycle tests:

    • completion closes and exits 0, verified;
    • Esc, Q and window close quit;
    • pause works;
    • Ctrl+C in the viewer loop and during setup exits 130 in under 1 s;
    • double Ctrl+C exits at once;
    • no GL errors and no leftover window.

    These cover Part 1 on CPU and Part 2 MJWarp on cuda:0, plus 9 Ctrl+C tests.

  • Headless matrix from notebooks/mujoco: Part 1 and Part 2 × so101/rebot × stack/box all exit 0 with a verified result. Untouched student scaffolds exit 1 at their first TODO.

  • solutions/so101_mjwarp_solution.py --benchmark --nworld 2048 --steps 200: exit 0.

Not tested: Docker/Brev container build, Colab, an NVIDIA-GLX desktop X session (none available; the earlier NVIDIA desktop record covers the same window code), macOS GUI (the "use python, not mjpython" guard is unchanged), Windows, and lower-end GPUs (RTX 3060 / 5090 runs by the tester are pending).

A tester following two sets of setup instructions got stuck on "Cannot download into non-empty ~/.cache/mujoco_menagerie": the cache held this Hub copy's versioned layout, which the imported helper refused, and the help text suggested exporting a folder he did not have.

Port NVIDIA-dev/newton_blogs#3 (merge 70ed6dc0874001f09ec706dbde790583349c1f5c). The automatic Menagerie cache is versioned by the pinned commit (the Hub layout, so existing Hub caches are reused), verified by Git, downloaded into a temporary folder and renamed into place; unverified caches are moved aside, never deleted. A MUJOCO_MENAGERIE_PATH without the robot folder is a one-line note, and offline or missing-git failures state the exact fix. Add doctor.py, a setup checker that prints a fix for every problem, and one local Quickstart in the tutorial README that the lesson guide links to. Tests cover the tester's cache, junk caches, offline runs and the doctor. The migration manifest records the source update; evidence keeps its original paths.

Signed-off-by: Johnny <johnnync13@gmail.com>
@johnnynunez

Copy link
Copy Markdown
Contributor Author

New head ab0f318 (GitHub-signed): port of NVIDIA-dev/newton_blogs#3 (merge 70ed6dc), so the first local run works without help.

Why: a tester ended up with an old ~/.cache/mujoco_menagerie and got "Cannot download into non-empty ~/.cache/mujoco_menagerie", plus help text telling him to export a MUJOCO_MENAGERIE_PATH he did not have. He had followed two different sets of setup instructions.

Changes in tutorials/sim2real-blogs:

  • Robot-model cache (part1/part2 utils.py, byte-identical to the source). The cache folder is named after the pinned commit, which is this Hub's existing layout, so existing Hub caches are reused. Git verifies the checkout. Downloads go into a temporary folder and are renamed into place. Unverified caches are moved aside, never deleted. A MUJOCO_MENAGERIE_PATH without the robot folder prints a one-line note, and offline or missing-git failures state the exact fix. pick_place_common.py re-points a stale assets symlink.
  • doctor.py (byte-identical to the source) checks Python, the lock versions, git, GPU/CUDA, display and robot models, and prints a fix: line for each problem.
  • One local Quickstart in README.md: uv, one install command, doctor, one command per part, expected output and how to quit, plus a conda alternative. notebooks/mujoco/README.md now links to it instead of repeating setup.
  • Tests: test/test_asset_cache.py (15: the tester's cache, junk/partial caches, offline, Hub/legacy layouts, atomic download) and test/test_doctor.py (3).
  • MIGRATION_MANIFEST.json records the source update (5 entries updated, 3 added). Evidence keeps its original paths.

Checked on the workstation (2x RTX PRO 6000, Xvfb):

  • pytest test/ with X11 and the CPU integration tests enabled: 181 passed, 1 skipped. One test_doctor run failed because I edited the README while the suite was running. Rerun on the final tree: test_doctor + test_asset_cache 18 passed.
  • Headless matrix (2 parts x 2 robots x stack/box): all Task complete, rc 0. Untouched scaffolds still fail honestly.
  • doctor.py in the Hub layout reports Ready and reuses the existing caches.
  • The same code in newton_blogs passed a brand-new-user run (empty HOME, Quickstart only), a conda run, the tester's exact cache, and offline runs. Details: https://github.com/NVIDIA-dev/newton_blogs/pull/3#issuecomment-6135654143

Not merging; this needs NVIDIA review.

@jnbntz
jnbntz merged commit 4087ee3 into NVIDIA:main Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants